package com.acmedcare.framework.exchange.center.core.handler;

import com.acmedcare.framework.exchange.center.core.Const;
import com.acmedcare.framework.exchange.center.core.PluginContainerMBean;
import com.acmedcare.framework.exchange.center.core.PluginMetadata;
import com.acmedcare.framework.exchange.center.core.consumer.ConsumerMetadata;
import com.acmedcare.framework.exchange.center.core.exception.ConsumerNotFoundException;
import com.acmedcare.framework.exchange.center.core.metadata.IDataConsumer;
import com.acmedcare.framework.exchange.center.entity.bean.Consumer;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.lang.reflect.Method;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ConsumerHandler implements ConsumerHandlerMBean {

  final ObjectMapper objectMapper;
  final PluginContainerMBean pluginContainer;
  final IAgentPublisher agentPublisher;

  public ConsumerHandler(ObjectMapper objectMapper,
      PluginContainerMBean pluginContainer,
      IAgentPublisher agentPublisher) {
    this.objectMapper = objectMapper;
    this.pluginContainer = pluginContainer;
    this.agentPublisher = agentPublisher;
  }

  @Override
  public void invoke(String msg,Consumer consumer) {

    try {

      PluginMetadata metadata = pluginContainer.getPlugin(consumer.getPluginName());
      ConsumerMetadata consumerMetadata = metadata.getConsumerMap()
          .get(consumer.getConsumerName().toLowerCase());
      if (consumerMetadata == null) {

        log.error("尚未找到消费器，请确认采集器是否已经加载，消费器名称：" + consumer.getConsumerName() + "插件名称：" + consumer
            .getPluginName());
        return;
      }

      IDataConsumer<Object> dataConsumer;

      if (consumerMetadata.getInstance() == null) {

        dataConsumer = (IDataConsumer<Object>) consumerMetadata
            .getConsumerClass()
            .newInstance();
        consumerMetadata.setInstance(dataConsumer);
      } else {

        dataConsumer = consumerMetadata.getInstance();
      }

      Class<?> type = dataConsumer.getEntityClass();
      //如果拿出来的是object类型，则再次解析当前类型确保获取正确的类型
      if (type == null || type.getName().equals(Object.class.getName())) {

        type = getParameterType(consumerMetadata.getConsumerClass(), "receive", 1);
      }

      if (type == null) {

        throw new ConsumerNotFoundException();
      }

      Object data= dataConsumer.receiveAndPublish(objectMapper.readValue(msg, type));
      if (data!=null){

        agentPublisher.publish(Const.TaskExchangePrefix+consumer.getName(),objectMapper.writeValueAsString(data));
      }
    } catch (Exception e) {

      log.error("执行数据消费器异常,消费者名称：" + consumer.getName(), e);
    }
  }


  private Class<?> getParameterType(Class<?> targetClass, String methodName, int parameterCount) {

    Method[] methodArray = targetClass.getDeclaredMethods();
    for (Method method : methodArray) {
      if (methodName.equals(method.getName())) {
        if (method.getParameterCount() == parameterCount
            && !method.getParameterTypes()[0].getName().equals(Object.class.getName())) {
          return method.getParameterTypes()[0];
        }
      }
    }

    return null;
  }
}
